package jnpf.base.controller;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.CaseFormat;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jnpf.base.ActionResult;
import jnpf.base.Page;
import jnpf.base.model.dbtable.dto.DbTableFieldDTO;
import jnpf.base.model.dbtable.vo.DbFieldVO;
import jnpf.base.model.dbtable.vo.DbTableInfoVO;
import jnpf.base.service.DbTableService;
import jnpf.base.vo.DownloadVO;
import jnpf.base.vo.ListVO;
import jnpf.base.vo.PageListVO;
import jnpf.base.vo.PaginationVO;
import jnpf.config.ConfigValueUtil;
import jnpf.constant.MsgCode;
import jnpf.database.model.dbfield.DbFieldModel;
import jnpf.database.model.dbtable.DbTableFieldModel;
import jnpf.database.model.page.DbTableDataForm;
import jnpf.database.sql.util.SqlFrameUtil;
import jnpf.exception.DataException;
import jnpf.print.entity.PrintDevEntity;
import jnpf.util.*;
import jnpf.util.enums.ModuleTypeEnum;
import jnpf.util.file.FileExport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据建模
 * N:方法说明 - 微服务同步使用
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Api(tags = "数据建模", value = "DataModel")
@RestController
@RequestMapping("/api/system/DataModel")
@Slf4j
public class DbTableController {

    @Autowired
    private DbTableService dbTableService;
    @Autowired
    private FileExport fileExport;
    @Autowired
    private ConfigValueUtil configValueUtil;

    /**
     * 1:列表
     *
     * @param id 连接id
     * @param page 关键词
     * @return 数据库表列表
     * @throws DataException ignore
     */
    @ApiOperation("获取数据库表列表")
    @GetMapping("/{id}/Tables")
    public ActionResult<ListVO<DbTableFieldModel>> getList(@PathVariable("id") String id, Page page) throws Exception {
        List<DbTableFieldModel> data = dbTableService.getList(XSSEscape.escape(id));
        if(StringUtil.isNotEmpty(page.getKeyword())){
            // 过滤不符条件的元素
            String keyWord = SqlFrameUtil.keyWordTrim(page.getKeyword()).toLowerCase();
            data = data.stream().filter(t->
                    (StringUtil.isNotEmpty(t.getComment()) && t.getComment().toLowerCase().contains(keyWord))
                    || t.getTable().toLowerCase().contains(keyWord)
            ).collect(Collectors.toList());
        }
        ListVO<DbTableFieldModel> vo = new ListVO<>();
        vo.setList(data);
        return ActionResult.success(vo);
    }

    /**
     * 2:预览数据库表
     *
     * @param dbTableDataForm 查询条件
     * @param linkId 接Id
     * @param tableName 表名
     * @return 数据库表
     * @throws Exception ignore
     */
    @ApiOperation("预览数据库表")
    @GetMapping("/{linkId}/Table/{tableName}/Preview")
    public ActionResult<PageListVO<Map<String, Object>>> data(DbTableDataForm dbTableDataForm, @PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws Exception {
        String escape = XSSEscape.escape(linkId);
        String escapeTableName = XSSEscape.escape(tableName);
        List<Map<String, Object>> data = dbTableService.getData(dbTableDataForm, escape, escapeTableName);
        PaginationVO paginationVO = JsonUtilEx.getJsonToBeanEx(dbTableDataForm, PaginationVO.class);
        return ActionResult.page(data, paginationVO);
    }

    /**
     * 3:列表
     *
     * @param linkId 数据连接ID
     * @param tableName 表名
     * @return 列表
     * @throws DataException ignore
     */
    @GetMapping("/{linkId}/Tables/{tableName}/Fields/Selector")
    @ApiOperation("获取数据库表字段下拉框列表")
    public ActionResult<ListVO<DbFieldVO>> selectorList(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws Exception {
        List<DbFieldModel> data = dbTableService.getFieldList(linkId, tableName);
        List<DbFieldVO> vos = JsonUtil.getJsonToList(data, DbFieldVO.class);
        ListVO<DbFieldVO> vo = new ListVO<>();
        vo.setList(vos);
        return ActionResult.success(vo);
    }

    /**
     * 4:字段列表
     *
     * @param linkId 连接Id
     * @param tableName 表名
     * @param type 类型
     * @return 段列表
     * @throws DataException ignore
     */
    @ApiOperation("获取数据库表字段列表")
    @GetMapping("/{linkId}/Tables/{tableName}/Fields")
    public ActionResult<ListVO<DbFieldVO>> fieldList(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName, String type) throws Exception {
        List<DbFieldModel> data = dbTableService.getFieldList(linkId, tableName);
        List<DbFieldVO> voList = data.stream().map(DbFieldVO::new).collect(Collectors.toList());
        for (DbFieldVO vo : voList) {
            if ("1".equals(type)) {
                String name = vo.getField().toLowerCase().replaceAll("f_", "");
                vo.setField(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name));
            }
        }
        ListVO<DbFieldVO> vo = new ListVO<>();
        vo.setList(voList);
        return ActionResult.success(vo);
    }

    /**
     * 5:编辑显示 - 表、字段信息
     *
     * @param dbLinkId 连接Id
     * @param tableName  表名
     * @return 表、字段信息
     * @throws DataException ignore
     */
    @ApiOperation("获取数据表")
    @GetMapping("/{dbLinkId}/Table/{tableName}")
    public ActionResult<DbTableInfoVO> get(@PathVariable("dbLinkId") String dbLinkId, @PathVariable("tableName") String tableName) throws Exception {
        return ActionResult.success(new DbTableInfoVO(dbTableService.getTable(dbLinkId, tableName), dbTableService.getFieldList(dbLinkId, tableName)));
    }

    /**
     * 6:新建表
     *
     * @param linkId 连接Id
     * @return 执行结果
     * @throws DataException ignore
     */
    @ApiOperation("新建")
    @PostMapping("{linkId}/Table")
    public ActionResult<String> create(@PathVariable("linkId") String linkId, @RequestBody @Valid DbTableFieldDTO dbTableFieldDTO) throws Exception {
        int status = dbTableService.createTable(dbTableFieldDTO.getCreDbTableModel(linkId));
        if (status == 1) {
            return ActionResult.success(MsgCode.SU001.get());
        } else if (status == 0) {
            return ActionResult.fail("表名称不能重复");
        } else {
            return ActionResult.fail("添加失败");
        }
    }

    /**
     * 7:更新
     *
     * @param linkId 连接Id
     * @return 执行结果
     * @throws DataException ignore
     */
    @ApiOperation("更新")
    @PutMapping("/{linkId}/Table")
    public ActionResult<String> update(@PathVariable("linkId") String linkId, @RequestBody @Valid DbTableFieldDTO dbTableFieldDTO) throws Exception {
            DbTableFieldModel dbTableModel = dbTableFieldDTO.getUpDbTableModel(linkId);
        // 当修改表名时，验证是否与其他表名重名
        if(!dbTableModel.getUpdateNewTable().equals(dbTableModel.getUpdateOldTable())){
            if(dbTableService.isExistTable(linkId, dbTableModel.getUpdateNewTable())){
                return ActionResult.fail("表名称不能重复");
            }
        }
        dbTableService.update(dbTableModel);
        return ActionResult.success(MsgCode.SU004.get());
    }

    /**
     * 8:更新
     *
     * @param linkId 连接Id
     * @return 执行结果
     * @throws DataException ignore
     */
    @ApiOperation("添加字段")
    @PutMapping("/{linkId}/addFields")
    public ActionResult<String> addField(@PathVariable("linkId") String linkId, @RequestBody @Valid DbTableFieldDTO dbTableFieldDTO) throws Exception {
        DbTableFieldModel dbTableModel = dbTableFieldDTO.getUpDbTableModel(linkId);
        dbTableService.addField(dbTableModel);
        return ActionResult.success(MsgCode.SU004.get());
    }

    /**
     * 9:删除
     *
     * @param linkId 连接Id
     * @param tableName 表名
     * @return 执行结果
     * @throws DataException ignore
     */
    @ApiOperation("删除")
    @DeleteMapping("/{linkId}/Table/{tableName}")
    public ActionResult<String> delete(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws Exception {
        dbTableService.delete(linkId, tableName);
        return ActionResult.success(MsgCode.SU003.get());
    }

    /**
     * 10:导入
     *
     * @param linkId 连接id
     * @param multipartFile 文件
     * @return 执行结果
     * @throws DataException ignore
     */
    @ApiOperation("导入")
    @PostMapping(value = "/{linkId}/Action/Import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ActionResult<PageListVO<PrintDevEntity>> importData(@PathVariable String linkId, @RequestPart("file") MultipartFile multipartFile) throws Exception {
        //判断是否为.json结尾
        if (FileUtil.existsSuffix(multipartFile, ModuleTypeEnum.SYSTEM_DBTABLE.getTableName())) {
            return ActionResult.fail(MsgCode.IMP002.get());
        }
        //读取文件内容
        String fileContent = FileUtil.getFileContent(multipartFile);
        DbTableFieldModel dbTableFieldModel = JSONObject.parseObject(fileContent, DbTableFieldModel.class);
        dbTableFieldModel.setDbLinkId(linkId);
        int i = dbTableService.createTable(dbTableFieldModel);
        if(i == 1){
            return ActionResult.success(MsgCode.IMP001.get());
        }else {
            return ActionResult.fail(MsgCode.DB007.get());
        }
    }

    /**
     * 11:导出
     *
     * @param tableName 表明
     * @param linkId 连接id
     * @return 执行结果
     */
    @ApiOperation("导出")
    @GetMapping("/{linkId}/Table/{tableName}/Action/Export")
    public ActionResult<DownloadVO> export(@PathVariable String tableName, @PathVariable String linkId) throws Exception {
        DbTableFieldModel dbTable = dbTableService.getDbTableModel(linkId, tableName);
        //导出文件
        DownloadVO downloadVO = fileExport.exportFile(dbTable, configValueUtil.getTemporaryFilePath(),
                dbTable.getTable() + "_", ModuleTypeEnum.SYSTEM_DBTABLE.getTableName());
        return ActionResult.success(downloadVO);
    }

}
